﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel;

using EasyProp.Extensions;
using Castle.Core.Interceptor;

namespace EasyProp
{
    public class NotifyPropertyChanged : IPropertySetterFilter
    {
        #region IPropertySetterFilter Members

        public bool Execute(IInvocation invocation, string propertyName)
        {
            FieldInfo fieldInfo;            
            if (TryGetFieldHoldingPropertyChangedDelegateList(invocation, out fieldInfo))
            {
                PropertyChangedEventHandler eventHandler = fieldInfo.GetValue(invocation.InvocationTarget) as PropertyChangedEventHandler;
                if (eventHandler != null)
                {
                    eventHandler.Invoke(invocation.InvocationTarget, new PropertyChangedEventArgs(propertyName));
                }
            }
            return true;
        }

        private static bool TryGetFieldHoldingPropertyChangedDelegateList(IInvocation invocation, out FieldInfo fieldInfo)
        {
            fieldInfo = null;

            Type typeToSearch = invocation.TargetType;

            // Search upwards in the inheritance hierarchy.
            while (fieldInfo == null && typeToSearch != null)
            {
                fieldInfo = typeToSearch.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
                    .Where(f => f.FieldType == typeof(PropertyChangedEventHandler))
                    .FirstOrDefault();

                typeToSearch = typeToSearch.BaseType;
            }

            return fieldInfo != null;
        }

        #endregion
    }
}
